extends AudioStreamPlayer

# 录音设置
const TARGET_SAMPLE_RATE: int = 16000  # 服务器需要的采样率
const FRAME_SIZE: int = 1024  # 每帧样本数，与服务器一致

# 录音组件
var _mic_player: AudioStreamPlayer
var _capture_effect: AudioEffectCapture
var _record_bus: int
var _is_active: bool = false

# 重采样状态
var _resample_ratio: float
var _resample_buffer: PackedFloat32Array = []
var _input_sample_rate: int = 44100

func _ready():
	_mic_player = self
	_mic_player.stream = AudioStreamMicrophone.new()
	
	# 设置音频总线布局
	var bus_layout = load("res://audio/audio_bus.tres")
	if bus_layout:
		AudioServer.set_bus_layout(bus_layout)
	
	# 获取录音总线
	_record_bus = AudioServer.get_bus_index("Record")
	if _record_bus == -1:
		push_error("找不到 'Record' 音频总线")
		return
		
	# 静音防止回音
	AudioServer.set_bus_mute(_record_bus, true)
	
	_mic_player.bus = "Record"
	
	# 获取捕捉效果
	if AudioServer.get_bus_effect_count(_record_bus) > 0:
		_capture_effect = AudioServer.get_bus_effect(_record_bus, 0) as AudioEffectCapture
	else:
		push_error("录音总线上没有捕捉效果")
		return
	
	# 获取实际输入采样率
	_input_sample_rate = AudioServer.get_mix_rate()
	print("麦克风输入采样率: ", _input_sample_rate, " Hz")
	
	# 计算重采样比例
	_resample_ratio = float(TARGET_SAMPLE_RATE) / _input_sample_rate
	
	# 连接全局信号
	SherpaManager.recording_started.connect(_on_recording_started)
	SherpaManager.recording_stopped.connect(_on_recording_stopped)

func _on_recording_started():
	start_recording()

func _on_recording_stopped():
	stop_recording()

func start_recording():
	if _is_active:
		return
	
	print("激活麦克风输入...")
	
	# 确保麦克风播放器在录制状态
	_mic_player.play()
	
	# 清除捕捉缓冲区
	if _capture_effect:
		_capture_effect.clear_buffer()
		AudioServer.set_bus_effect_enabled(_record_bus, 0, true)
	
	_is_active = true
	_resample_buffer = []

func stop_recording():
	if !_is_active:
		return
	
	print("停用麦克风输入")
	
	# 停止麦克风播放
	_mic_player.stop()
	
	# 禁用捕捉效果
	if _capture_effect:
		AudioServer.set_bus_effect_enabled(_record_bus, 0, false)
	
	_is_active = false
	_resample_buffer = []

func _process(_delta):
	# 确保在活动状态
	if !_is_active || !_capture_effect || SherpaManager.state != SherpaManager.State.RECORDING:
		return
	
	# 获取可用帧数
	var frames_available = _capture_effect.get_frames_available()
	
	# 确保有足够的数据
	if frames_available < FRAME_SIZE:
		return
	
	# 获取音频数据
	var stereo_data = _capture_effect.get_buffer(FRAME_SIZE)
	
	# 转换为单声道
	var mono_data = _convert_to_mono(stereo_data)
	
	# 添加到重采样缓冲区
	_resample_buffer.append_array(mono_data)
	
	# 重采样并发送帧
	_resample_and_send_frame()

func _convert_to_mono(stereo_data: PackedVector2Array) -> PackedFloat32Array:
	var mono = PackedFloat32Array()
	mono.resize(stereo_data.size())
	
	for i in range(stereo_data.size()):
		# 左右声道平均
		mono[i] = (stereo_data[i].x + stereo_data[i].y) * 0.5
	
	return mono

func _resample_and_send_frame():
	# 计算目标样本数
	var target_size: int = floor(_resample_buffer.size() * _resample_ratio)
	
	# 确保有足够的数据生成一帧
	if target_size < FRAME_SIZE:
		return
	
	# 重采样
	var resampled = _resample(_resample_buffer, _resample_ratio, FRAME_SIZE)
	
	# 发送帧
	SherpaManager.send_audio_frame(resampled)
	
	# 清除已处理数据
	var consumed = ceil(FRAME_SIZE / _resample_ratio)
	if consumed < _resample_buffer.size():
		_resample_buffer = _resample_buffer.slice(consumed)
	else:
		_resample_buffer = []

func _resample(source: PackedFloat32Array, ratio: float, output_size: int) -> PackedFloat32Array:
	var result = PackedFloat32Array()
	result.resize(output_size)
	
	for i in range(output_size):
		var src_index = i / ratio
		var index0 = floor(src_index)
		var index1 = min(ceil(src_index), source.size() - 1)
		var fraction = src_index - index0
		
		# 线性插值
		var sample = lerp(
			source[index0],
			source[index1],
			fraction
		)
		result[i] = sample
	
	return result
